/* 
 * Copyright 2010 Ziya Guven Koylu, Ozge Koylu
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.koylu.caffein.model.handler;

import java.lang.reflect.Method;

import javassist.util.proxy.MethodHandler;

import com.koylu.caffein.javassist.BeanGenerator;
import com.koylu.caffein.model.caffein.CaffeinConfig;
import com.koylu.caffein.model.clazz.Clazz;

public class ManyToOneContainerHandler implements MethodHandler {

	private CaffeinConfig caffeinConfig;
	private Clazz clazz;
	private Object id;
	private Object originalId;
	private Object lazyLoadedObject;
	private String idReadMethodName;
	private String idWriteMethodName;

	public ManyToOneContainerHandler(CaffeinConfig caffeinConfig, Clazz clazz, Object id) throws Exception{
		this.caffeinConfig = caffeinConfig;
		this.clazz = clazz;
		this.id = id;
		this.originalId = id;
		String formattedFieldName = BeanGenerator.formatField(clazz.getId().getName());
		this.idReadMethodName = "get"+formattedFieldName;
		this.idWriteMethodName = "set"+formattedFieldName;
	}

	public Object invoke(Object object, Method method, Method proceed, Object[] args) throws Throwable {
		String methodName = method.getName();
		if(clazz.isReadonly()){
			if (methodName.startsWith("set")) {
				return null;
			}
		}
		if (methodName.equals(idReadMethodName)) {
			return id;
		}
		if (lazyLoadedObject == null) {
			if(id != null){
				lazyLoadedObject = caffeinConfig.getCaffein().load(clazz, id);
			}
			if(lazyLoadedObject == null){
				lazyLoadedObject = clazz.toEmptyObject(caffeinConfig);
			}
		}
		if (methodName.equals(idWriteMethodName)) {
			id = args[0];
		}else if(methodName.equals("isContainerIdUpdated")){
			if(originalId == null){
				return id != null;
			}else if(id  == null){
				return true;
			}
			return !clazz.getId().toUniqueId(caffeinConfig, originalId).equals(clazz.getId().toUniqueId(caffeinConfig, id));
		}
		return method.invoke(lazyLoadedObject, args);
	}
}